package com.atguigu.tingshu.search.service.impl;

import com.atguigu.tingshu.album.AlbumFeignClient;
import com.atguigu.tingshu.common.constant.RedisConstant;
import com.atguigu.tingshu.common.execption.GuiguException;
import com.atguigu.tingshu.common.result.Result;
import com.atguigu.tingshu.common.result.ResultCodeEnum;
import com.atguigu.tingshu.model.album.AlbumInfo;
import com.atguigu.tingshu.model.album.BaseCategoryView;
import com.atguigu.tingshu.search.service.ItemService;
import com.atguigu.tingshu.user.client.UserFeignClient;
import com.atguigu.tingshu.vo.album.AlbumStatVo;
import com.atguigu.tingshu.vo.user.UserInfoVo;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RBloomFilter;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Service;

import java.util.Map;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ThreadPoolExecutor;

@Slf4j
@Service
public class ItemServiceImpl implements ItemService {
    private final AlbumFeignClient albumFeignClient;
    private final UserFeignClient userFeignClient;
    private final ThreadPoolExecutor threadPoolExecutor;
    private final RedissonClient redissonClient;

    public ItemServiceImpl(AlbumFeignClient albumFeignClient, UserFeignClient userFeignClient, ThreadPoolExecutor threadPoolExecutor, RedissonClient redissonClient) {
        this.albumFeignClient = albumFeignClient;
        this.userFeignClient = userFeignClient;
        this.threadPoolExecutor = threadPoolExecutor;
        this.redissonClient = redissonClient;
    }


    @Override
    public Map<String, Object> getAlbumDetailByAlbumId(Long albumId) {
        // 根据布隆过滤器判断专辑是否存在
        RBloomFilter<Long> bloomFilter = this.redissonClient.getBloomFilter(RedisConstant.ALBUM_BLOOM_FILTER);
        if (!bloomFilter.contains(albumId)) {
            throw new GuiguException(ResultCodeEnum.ALBUM_NOT_FOUND);
        }
        // 1.远程调用专辑服务获取专辑基本信息 albumInfo
        CompletableFuture<AlbumInfo> albumInfoFuture = CompletableFuture.supplyAsync(() -> {
            Result<AlbumInfo> result = albumFeignClient.getAlbumInfoById(albumId);
            if (ResultCodeEnum.FAIL.getCode().equals(result.getCode())) {
                throw new GuiguException(ResultCodeEnum.REMOTE_ERROR);
            }
            AlbumInfo albumInfo = result.getData();
            return Optional.ofNullable(albumInfo).orElseGet(() -> {
                log.error("专辑不存在，专辑ID：{}", albumId);
                return new AlbumInfo();
            });
        }, threadPoolExecutor);

        // 2.远程调用用户服务获取专辑主播信息 announcer
        CompletableFuture<UserInfoVo> announcerFuture = albumInfoFuture.thenApplyAsync(albumInfo -> {
            Result<UserInfoVo> result = userFeignClient.getUserInfoVoByUserId(albumInfo.getUserId());
            if (ResultCodeEnum.FAIL.getCode().equals(result.getCode())) {
                throw new GuiguException(ResultCodeEnum.REMOTE_ERROR);
            }
            UserInfoVo userInfoVo = result.getData();
            return Optional.ofNullable(userInfoVo).orElseGet(() -> {
                log.error("专辑主播不存在，主播ID：{}", albumInfo.getUserId());
                return new UserInfoVo();
            });
        }, threadPoolExecutor);

        // 3.远程调用专辑服务获取专辑分类信息 baseCategoryView
        CompletableFuture<BaseCategoryView> categoryViewFuture = albumInfoFuture.thenApplyAsync(albumInfo -> {
            Result<BaseCategoryView> result = albumFeignClient.getCategoryView(albumInfo.getCategory3Id());
            if (ResultCodeEnum.FAIL.getCode().equals(result.getCode())) {
                throw new GuiguException(ResultCodeEnum.REMOTE_ERROR);
            }
            BaseCategoryView baseCategoryView = result.getData();
            return Optional.ofNullable(baseCategoryView).orElseGet(() -> {
                log.error("专辑分类不存在，分类ID：{}", albumInfo.getCategory3Id());
                return new BaseCategoryView();
            });
        }, threadPoolExecutor);

        // 4.远程调用专辑服务获取专辑统计信息 albumStatVo
        CompletableFuture<AlbumStatVo> albumStatVoFuture = CompletableFuture.supplyAsync(() -> {
            Result<AlbumStatVo> result = albumFeignClient.getAlbumStatVo(albumId);
            if (ResultCodeEnum.FAIL.getCode().equals(result.getCode())) {
                throw new GuiguException(ResultCodeEnum.REMOTE_ERROR);
            }
            AlbumStatVo albumStatVo = result.getData();
            return Optional.ofNullable(albumStatVo).orElseGet(() -> {
                log.error("专辑统计不存在，专辑ID：{}", albumId);
                return new AlbumStatVo();
            });
        }, threadPoolExecutor);

        // 阻塞等待所有任务完成
        CompletableFuture.allOf(
                albumInfoFuture, announcerFuture, albumStatVoFuture, categoryViewFuture
        ).join();

        try {
            // 获取各个future的结果
            AlbumInfo albumInfo = albumInfoFuture.get();
            UserInfoVo announcer = announcerFuture.get();
            AlbumStatVo albumStatVo = albumStatVoFuture.get();
            BaseCategoryView baseCategoryView = categoryViewFuture.get();

            return Map.of(
                    "announcer", announcer,
                    "albumInfo", albumInfo,
                    "albumStatVo", albumStatVo,
                    "baseCategoryView", baseCategoryView
            );
        } catch (InterruptedException | ExecutionException e) {
            log.error("[检索服务]专辑详情服务异常：{}", e.getMessage(), e);
            throw new GuiguException(ResultCodeEnum.SERVICE_ERROR);
        }
    }

}
